package com.linguamathematica.oa4j;

import java.util.Set;

import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static com.linguamathematica.oa4j.Base.newSet;

import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import com.linguamathematica.oa4j.Analysis.Decisiveness;
import com.linguamathematica.oa4j.Analysis.OfferingGuidance;
import com.linguamathematica.oa4j.Analysis.Polarity;
import com.linguamathematica.oa4j.Analysis.PolarityResult;
import com.linguamathematica.oa4j.Analysis.RequestingGuidance;
import com.linguamathematica.oa4j.Analysis.Temporality;
import com.linguamathematica.oa4j.DemographicsAnalysis.Age;
import com.linguamathematica.oa4j.DemographicsAnalysis.Education;
import com.linguamathematica.oa4j.DemographicsAnalysis.Gender;
import com.linguamathematica.oa4j.DemographicsAnalysis.Language;
import com.linguamathematica.oa4j.StylesAnalysis.Contrast;
import com.linguamathematica.oa4j.StylesAnalysis.Flamboyance;
import com.linguamathematica.oa4j.StylesAnalysis.Slang;
import com.linguamathematica.oa4j.TopicsAnalysis.Domain;
import com.linguamathematica.oa4j.TopicsAnalysis.Noun;

public class AnalysisServiceTestGivenTextA extends AbstractAnalysisServiceTest
{
	private static String textA;

	@Test
	public void returns_CorrectActionsAnalysis() throws Exception
	{
		final ActionsAnalysis expected = actionsAnalysis(//@formatter:off
				
				action(topic("go", 6), of(Decisiveness.LOW, 1), of(OfferingGuidance.TO_SOME_EXTENT, 2),
						of(RequestingGuidance.NOT_AT_ALL, 1), type("travel", 1), of(Temporality.FUTURE, 4)),

				action(topic("take", 6), of(Decisiveness.LOW, 1), of(OfferingGuidance.NOT_AT_ALL, 1),
						of(RequestingGuidance.NOT_AT_ALL, 1), type("other", 1), of(Temporality.PAST, 1)),

				action(topic("hunt", 4), of(Decisiveness.LOW, 1), of(OfferingGuidance.NOT_AT_ALL, 1),
						of(RequestingGuidance.NOT_AT_ALL, 1), type("attack", 1), of(Temporality.PAST, 1)),

				action(topic("find the money", 3), of(Decisiveness.LOW, 1), of(OfferingGuidance.NOT_AT_ALL, 1),
						of(RequestingGuidance.NOT_AT_ALL, 1), type("other", 1), of(Temporality.PRESENT, 3)),

				action(topic("get", 3), of(Decisiveness.LOW, 1), of(OfferingGuidance.NOT_AT_ALL, 1),
						of(RequestingGuidance.NOT_AT_ALL, 1), type("other", 1), of(Temporality.PAST, 1)));//@formatter:on

		assertThat(actionsAnalysisOf(textA), is(as(expected)));
	}

	@Test
	public void returns_CorrectDemographicsAnalysis() throws Exception
	{
		final DemographicsAnalysis expected = demographics(of(Age.ADULT, .01), of(Gender.NEUTRAL, 0),
				of(Education.PRE_SECONDARY, 1), of(Language.ENGLISH, 24.49));

		assertThat(demographicAnalysisOf(textA), is(as(expected)));
	}

	@Test
	public void returns_CorrectDomains() throws Exception
	{
		final Set<Domain> expected = newSet(//@formatter:off
				new Domain(topic("Family", 1), new Domain(topic("Immediate family", 1), new Domain(topic("son", 1), Domain.NULL))),
				new Domain(topic("Relationships", 12), new Domain(topic("widow", 12), Domain.NULL)),
				new Domain(topic("Politics", 6.0), new Domain(topic("Politicians", 6.0), new Domain(topic("douglas", 6.0), Domain.NULL))));
		//@formatter:on
		assertThat(domainsIn(textA), are(as(expected)));
	}

	@Test
	public void returns_CorrectLocations() throws Exception
	{
		final Set<Analysis.Result<String>> expected = newSet();

		assertThat(locationsIn(textA), are(as(expected)));
	}

	@Test
	public void returns_CorrectProperNouns() throws Exception
	{
		final Set<Noun> expected = newSet(//@formatter:off

				properNoun(topic("Judge Thatcher", 12), of(Polarity.NEUTRAL, 0), of(OfferingGuidance.TO_SOME_EXTENT, 2),
						of(RequestingGuidance.NOT_AT_ALL, 1), ner("Person", "female")),

				properNoun(topic("Tom Sawyer", 9), of(Polarity.NEUTRAL, 0), of(OfferingGuidance.NOT_AT_ALL, 1),
						of(RequestingGuidance.NOT_AT_ALL, 1), ner("Person", "male")),

				properNoun(topic("Tom", 7), of(Polarity.NEUTRAL, 0), of(OfferingGuidance.NOT_AT_ALL, 1),
						of(RequestingGuidance.NOT_AT_ALL, 1), ner("Person", "male")),
		
				properNoun(topic("Douglas", 6), of(Polarity.NEUTRAL, 0), of(OfferingGuidance.NOT_AT_ALL, 1),
						of(RequestingGuidance.NOT_AT_ALL, 1), ner("Person", "male")));//@formatter:on

		assertThat(properNounsIn(textA), are(as(expected)));
	}

	@Test
	public void returns_CorrectStyleAnalysis() throws Exception
	{
		final StylesAnalysis expected = style(of(Polarity.NEGATIVE, -.9), of(Polarity.NEGATIVE, -.01),
				of(Polarity.POSITIVE, .95), of(OfferingGuidance.A_LOT, 3), of(RequestingGuidance.NOT_AT_ALL, 1),
				of(Decisiveness.MEDIUM, 3), of(Slang.NO_SLANG, .57), of(Flamboyance.SOMEWHAT_FLAMBOYANT, 3),
				of(Contrast.NOT_AT_ALL, .19), of(Temporality.FUTURE, 4));

		assertThat(styleAnalysisOf(textA), is(as(expected)));
	}

	@Test
	public void returns_CorrectTopTopics() throws Exception
	{
		final Set<Noun> expected = newSet(//@formatter:off

				topTopic(topic("widow", 12), new PolarityResult(of(Polarity.NEUTRAL, 0),of(Polarity.POSITIVE, .92),of(Polarity.POSITIVE, .95)),
						of(OfferingGuidance.TO_SOME_EXTENT, 2),of(RequestingGuidance.NOT_AT_ALL, 1)),

				topTopic(topic("Judge Thatcher", 12), of(Polarity.NEUTRAL, 0), 
						of(OfferingGuidance.TO_SOME_EXTENT, 2),of(RequestingGuidance.NOT_AT_ALL, 1), ner("Person", "female")),

				topTopic(topic("Tom Sawyer", 9), of(Polarity.NEUTRAL, 0), 
						of(OfferingGuidance.NOT_AT_ALL, 1),of(RequestingGuidance.NOT_AT_ALL, 1), ner("Person", "male")),

				topTopic(topic("Tom", 7), of(Polarity.NEUTRAL, 0), 
						of(OfferingGuidance.NOT_AT_ALL, 1),of(RequestingGuidance.NOT_AT_ALL, 1), ner("Person", "male")),

				topTopic(topic("money", 6),new PolarityResult(of(Polarity.NEGATIVE, -.89),of(Polarity.NEGATIVE, -.89),of(Polarity.NEUTRAL, 0)),
						of(OfferingGuidance.NOT_AT_ALL, 1),of(RequestingGuidance.NOT_AT_ALL, 1)));//@formatter:on

		assertThat(topTopicsIn(textA), are(as(expected)));
	}

	@Before
	public void setUpEveryTime() throws Exception
	{
		httpService = mock(HTTPService.class);
		mockResponseFor(textA, "OAResponseToTestText_A.xml");
		service = new DefaultAnalysisService(key, httpService);
	}

	@BeforeClass
	public static void setUpOnce() throws Exception
	{
		textA = loadFrom("TestText_A.txt");
	}
}
